/*
 * Copyright (c) 2013. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
 * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
 * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
 * Vestibulum commodo. Ut rhoncus gravida arcu.
 */

package com.jspx.txweb;


import com.jspx.boot.environment.Environment;
import com.jspx.network.http.HttpClient;
import com.jspx.network.http.HttpClientFactory;
import com.jspx.txweb.action.BaseUserAction;
import com.jspx.txweb.annotation.HttpMethod;
import com.jspx.txweb.env.TXWeb;
import com.jspx.utils.StringUtil;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Created with IntelliJ IDEA.
 * User: yuan
 * Date: 13-1-10
 * Time: 下午8:45
 * 登陆本构架的接口 OAuth
 */
@HttpMethod(caption = "远程登录接口")
public class OAuthClient extends BaseUserAction {

    //默认创建一个模拟 浏览器，在应用程序中使用，要创建为全局变量

    public static final String encode = Environment.defaultEncode;

    public static final String KEY_loginField = "field";
    public static final String KEY_loginId = "loginId";
    public static final String KEY_timeMillis = "timeMillis";
    public static final String KEY_password = "password";
    public static final String KEY_passwordEncoded = "passwordEncoded";
    public static final String KEY_verify = "verify";
    public static final String KEY_sessionId = "sessionId";
    public static final String KEY_mode = "mode";


    final public static String KEY_publicKeyUrl = "publicKeyUrl";
    final public static String KEY_remoteLoginUrl = "remoteLoginUrl";
    final public static String KEY_checkSessionUrl = "checkSessionUrl";
    final public static String KEY_exitSessionUrl = "exitSessionUrl";
    final public static String KEY_postWorkersUrl = "postWorkersUrl";
    final public static String KEY_postUploadUrl = "postUploadUrl";

    final public static String KEY_clientConfigUrl = "clientConfigUrl";
    final public static String KEY_clientDownloadUrl = "clientDownloadUrl";

    final public static String KEY_privateKey = "privateKey";
    //在实际使用中，将IP换成你应用服务器IP或域名

    public static String publicKeyUrl = StringUtil.empty;
    public static String remoteLoginUrl = StringUtil.empty;
    public static String checkSessionUrl = StringUtil.empty;
    public static String exitSessionUrl = StringUtil.empty;
    public static String clientConfigUrl = StringUtil.empty;
    public static String clientDownloadUrl = StringUtil.empty;
    public static String postWorkersUrl = StringUtil.empty;
    public static String postUploadUrl = StringUtil.empty;
    public static final String mode = "mode";

    private HttpClient httpClient = null;
    /**
     * 公密史动态的，会变动的
     *
     * @return 得到公密, jspx.net应用中必须公密+私密的方式才能使用，这里得到公密
     * @throws Exception
     */
    public static String getNetPublicKey() throws Exception {
        HttpClient httpClient = HttpClientFactory.createHttpClient(publicKeyUrl);
        return StringUtil.trim(httpClient.post(null));
    }

    /**
     * 模拟浏览器完成登陆操作，客户端网页可以做一个按钮链接发送以下信息
     *
     * @param postParameter 登陆参数
     * @return 登陆后的信息
     * @throws Exception
     */
    public static String login(Map<String, Object> postParameter) throws Exception {
        return HttpClientFactory.createHttpClient(remoteLoginUrl).post(postParameter);
    }


    /**
     * 通过登录后得到的sessionId可以判断是否为在线状态
     *
     * @param sessionId 用户登录后得到
     * @return 判断是否已经登录在线, 0 表示否，1表示 是
     * @throws Exception
     */
    public static int isOnline(String sessionId) throws Exception {
        Map<String,Object> valueMap = new HashMap<String,Object>();
        valueMap.put(TXWeb.sessionId, sessionId);
        return StringUtil.toInt(StringUtil.trim(HttpClientFactory.createHttpClient(checkSessionUrl).getString(valueMap)));
    }

    /**
     * 注销登录状态
     *
     * @param sessionId 用户登录后得到
     * @return 退出
     * @throws Exception
     */
    public static int exit(String sessionId) throws Exception {
        Map<String,Object> valueMap = new HashMap<String,Object>();
        valueMap.put(KEY_sessionId, sessionId);
        return StringUtil.toInt(StringUtil.trim(HttpClientFactory.createHttpClient(exitSessionUrl).getString(valueMap)));
    }

    public static String post(String url, Map<String, Object> postParameter) throws Exception {
        return HttpClientFactory.createHttpClient(url).post(postParameter);
    }

    public static String get(String url, Map<String, Object> postParameter) throws Exception {
        return HttpClientFactory.createHttpClient(url).getString(postParameter);
    }

    public static String upload(String url, Map<String, String> params, List<File> files) throws IOException
    {
        StringBuilder result = new StringBuilder();
        String BOUNDARY = java.util.UUID.randomUUID().toString();
        String PREFIX = "--", LINEND = StringUtil.CRLF;
        String MULTIPART_FROM_DATA = "multipart/form-data";
        URL uri = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) uri.openConnection();

        conn.setReadTimeout(5 * 1000);
        conn.setDoInput(true);// 允许输入
        conn.setDoOutput(true);// 允许输出
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");  //Post方式
        conn.setRequestProperty("connection", "keep-alive");
        conn.setRequestProperty("Charsert", encode);
        conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);


        // 首先组拼文本类型的参数
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            sb.append(PREFIX);
            sb.append(BOUNDARY);
            sb.append(LINEND);
            sb.append("Content-Disposition: form-data; name=\"").append(entry.getKey()).append("\"").append(LINEND);
            sb.append("Content-Type: text/plain; charset=").append(encode).append(LINEND);
            sb.append("Content-Transfer-Encoding: 8bit").append(LINEND);
            sb.append(LINEND);
            sb.append(entry.getValue());
            sb.append(LINEND);
        }

        DataOutputStream outStream = new DataOutputStream(conn
                .getOutputStream());
        outStream.write(sb.toString().getBytes());
        // 发送文件数据
        if (files != null)
            for (File file : files) {
                StringBuilder sb1 = new StringBuilder();
                sb1.append(PREFIX);
                sb1.append(BOUNDARY);
                sb1.append(LINEND);
                sb1.append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(file.getName()).append("\"").append(LINEND);
                sb1.append("Content-Type: application/octet-stream; charset=").append(encode).append(LINEND);
                sb1.append(LINEND);
                outStream.write(sb1.toString().getBytes());

                InputStream is = new FileInputStream(file);
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = is.read(buffer)) != -1) {
                    outStream.write(buffer, 0, len);
                }

                is.close();
                outStream.write(LINEND.getBytes());
            }

        // 请求结束标志
        byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
        outStream.write(end_data);
        outStream.flush();

        // 得到响应码
        int res = conn.getResponseCode();
        if (res==200)
        {
            BufferedReader input = new BufferedReader(new InputStreamReader(conn.getInputStream(), encode));
            int ss;
            while ((ss = input.read()) != -1) {
                result.append((char) ss);
            }
            input.close();
        }
        return result.toString();

    }

}
